Namespace Threads

    Friend MustInherit Class MultiVersionThread
        Inherits Threads.BikiThread

        Protected m_threadPurpose As String = "Action"
        Protected m_carBase As CarBase = Nothing
        Protected m_Action As BikiAction = BikiAction.BK_NONE
        Protected m_UsbCommHandler As Comm.UsbCommunicationHandle = Nothing

        Protected Enum _eAction As Byte
            NONE = 0
            BANK1 = 1
            BANK2 = 2
            TODO1 = 4
            TODO2 = 8
            VERIFIED = &H10
            COMPLETE = &H20
        End Enum
        Protected Structure typFlashSector
            Sub New(ByVal Address As ULong, ByVal Size As ULong)
                nAddress = Address
                nSize = Size
                eAction = _eAction.NONE
            End Sub
            Dim nAddress As ULong
            Dim nSize As ULong
            Dim nCrc As UInt32
            Dim nBank1CRC As UInt32
            'Dim nBank2CRC As UInt32
            Dim eAction As _eAction
        End Structure

        Public Enum thread_result
            rslt_allok
            rslt_allok_reset_required
            rslt_canceled
            rslt_comms_error
            rslt_board_fault
            rslt_bikisoft_error
            rslt_board_unsupported
        End Enum

        Protected HwV2Sectors()() As typFlashSector = New typFlashSector()() { _
                                                    New typFlashSector() {New typFlashSector(0, &H10000)}, _
                                                    New typFlashSector() {New typFlashSector(&H10000, &H10000)}, _
                                                    New typFlashSector() {New typFlashSector(&H20000, &H10000)}, _
                                                    New typFlashSector() { _
                                                        New typFlashSector(&H30000, &H8000), _
                                                        New typFlashSector(&H38000, &H2000), _
                                                        New typFlashSector(&H3A000, &H2000), _
                                                        New typFlashSector(&H3C000, &H4000)}}
        Protected HwV3Sectors()() As typFlashSector = New typFlashSector()() { _
                                                New typFlashSector() { _
                                                    New typFlashSector(&H0, &H4000), _
                                                    New typFlashSector(&H4000, &H2000), _
                                                    New typFlashSector(&H6000, &H2000), _
                                                    New typFlashSector(&H8000, &H8000)}, _
                                                New typFlashSector() {New typFlashSector(&H10000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H20000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H30000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H40000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H50000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H60000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H70000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H80000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H90000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&HA0000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&HB0000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&HC0000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&HD0000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&HE0000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&HF0000, &H10000)}}

        Protected HwV3TTSectors()() As typFlashSector = New typFlashSector()() { _
                                                New typFlashSector() {New typFlashSector(&H0, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H10000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H20000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H30000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H40000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H50000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H60000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H70000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H80000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&H90000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&HA0000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&HB0000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&HC0000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&HD0000, &H10000)}, _
                                                New typFlashSector() {New typFlashSector(&HE0000, &H10000)}, _
                                                New typFlashSector() { _
                                                    New typFlashSector(&HF0000, &H8000), _
                                                    New typFlashSector(&HF8000, &H2000), _
                                                    New typFlashSector(&HFA000, &H2000), _
                                                    New typFlashSector(&HFC000, &H4000)} _
                                                }

        'Protected HwV2SectorAddrs()() As ULong = New ULong()() { _
        '                                        New ULong() {&H0}, _
        '                                        New ULong() {&H10000}, _
        '                                        New ULong() {&H20000}, _
        '                                        New ULong() {&H30000, &H38000, &H3A000, &H3C000}}
        'Protected HwV3SectorAddrs()() As ULong = New ULong()() { _
        '                                        New ULong() {&H0, &H4000, &H6000, &H8000}, _
        '                                        New ULong() {&H10000}, _
        '                                        New ULong() {&H20000}, _
        '                                        New ULong() {&H30000}, _
        '                                        New ULong() {&H40000}, _
        '                                        New ULong() {&H50000}, _
        '                                        New ULong() {&H60000}, _
        '                                        New ULong() {&H70000}, _
        '                                        New ULong() {&H80000}, _
        '                                        New ULong() {&H90000}, _
        '                                        New ULong() {&HA0000}, _
        '                                        New ULong() {&HB0000}, _
        '                                        New ULong() {&HC0000}, _
        '                                        New ULong() {&HD0000}, _
        '                                        New ULong() {&HE0000}, _
        '                                        New ULong() {&HF0000}}
        Protected Const SectorSize As ULong = &H10000
        Protected Const BankSize As ULong = &H100000

        Protected mProgressMax As ULong = SectorSize
        Protected mProgressCurrent As ULong = 1

        Protected Sub New(ByVal Purpose As String)
            Me.m_threadPurpose = Purpose
        End Sub

        Friend Overloads Function Execute( _
        ByVal backGroundWorker As System.ComponentModel.BackgroundWorker, _
        ByVal e As System.ComponentModel.DoWorkEventArgs) As Boolean
            MyBase.Execute(backGroundWorker, e)

            Dim bStatus As thread_result = thread_result.rslt_allok
            Dim loops As Integer = 0

            If Not m_UsbCommHandler Is Nothing _
                    AndAlso m_UsbCommHandler.IsConnected _
                    AndAlso m_UsbCommHandler.Initialised Then
                Try
                    m_UsbCommHandler.Timeout = 50

                    OnMessage(m_threadPurpose & " started!")

                    Select Case m_UsbCommHandler.UsbInformation.BoardVersion
                        Case 1, 2
                            bStatus = HwV2Process()
                        Case 3
                            'Console.WriteLine("REMOVE THIS ENDLESS LOOP YOU IDIOT")
                            'While True
                            '    loops += 1
                            bStatus = HwV3Process()
                            'OnMessage("Performing Loop " & loops)
                            'End While
                        Case 4
                            bStatus = HwV4Process()
                    End Select

                    OnProgress(100)

                    e.Result = bStatus
                Catch ex As USB_exceptions
                    e.Result = thread_result.rslt_comms_error
                    OnMessage("!Communication Failed, " & m_threadPurpose & " not complete")
                Catch ex As Exception
                    e.Result = thread_result.rslt_bikisoft_error
                    OnMessage("!BikiSoft Error occured, general exception")
                End Try
            Else
                e.Result = thread_result.rslt_comms_error
                OnMessage("!Communication not initialised")
            End If
        End Function

        ''' <summary>
        ''' Functions adds the progress to the current progress counter and reports it back to the
        ''' main threads
        ''' </summary>
        ''' <param name="Progress"></param>
        ''' <remarks></remarks>
        Protected Sub IncrementProgress(ByVal Progress As ULong)
            mProgressCurrent += Progress
            OnProgress((mProgressCurrent * 100) / mProgressMax)
        End Sub

        ''' <summary>
        ''' Performs a Upload given the action and the data for a Bikirom Version 2 Hardware Board
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        MustOverride Function HwV2Process() As thread_result

        MustOverride Function HwV3Process() As thread_result

        MustOverride Function HwV4Process() As thread_result

        Protected Sub CalculateCrc(ByRef Data() As Byte, ByVal sectors As typFlashSector())
            If IsNothing(Data) Then
                For i As Integer = 0 To UBound(sectors)
                    sectors(i).nCrc = &HFFFFFFFFUI
                Next
            Else
                Dim crc32 As New libCRC32
                Dim offset As UInteger = 0
                For i As Integer = 0 To UBound(sectors)
                    If i = 0 Then
                        sectors(i).nCrc = crc32.GetByteArrayCrc32(Data, 16, sectors(i).nSize)
                    Else
                        sectors(i).nCrc = crc32.GetByteArrayCrc32(Data, offset, sectors(i).nSize)
                    End If

                    ' Copy in the CRC
                    Array.Copy(System.BitConverter.GetBytes(sectors(i).nCrc), 0, Data, i * 4, 4)

                    offset += sectors(i).nSize
                Next

                ' Nuke the first locations!
                For i As Integer = 0 To UBound(sectors)
                    Array.Copy(System.BitConverter.GetBytes(&HFFFFFFFFUI), 0, Data, i * 4, 4)
                Next
            End If
        End Sub

        Protected Function downloadCrcs(ByVal Sectors As typFlashSector(), Optional ByVal Bank As Integer = 0) As Boolean
            Dim packetSize As UInt16 = (Sectors.Length * 4)
            Dim data(packetSize - 1) As Byte
            Dim packetData(packetSize - 1) As Byte
            Dim rcvData() As Byte = Nothing
            Dim frame As Comm.Comm_Frame = Nothing
            Dim packetAdr As ULong = 0

            Try
                m_UsbCommHandler.Timeout = 1000

                ' Retrieve crc's from Bank 1
                If Bank = -1 Or Bank = 0 Then
                    packetAdr = Sectors(0).nAddress
                    frame = New Comm.Comm_Frame(Comm.Comm_Frame.BikiFrameType.ID_FLASH_DATA _
                                                                          , packetAdr _
                                                                          , Comm.Comm_Frame.BikiFrameAction.READ, packetData, Comm.Comm_Frame.BikiFrameType.ID_FLASH_DATA)
                    If m_UsbCommHandler.SendFrame(frame, rcvData, , 10) = Comm.Comm_Frame.BikiFrameResponse.CMD_OK AndAlso Not IsNothing(rcvData) Then
                        Array.Copy(rcvData, 5, data, 0, packetSize)
                        For i As Integer = 0 To UBound(Sectors)
                            Sectors(i).nBank1CRC = System.BitConverter.ToUInt32(data, i * 4)
                        Next

                    End If
                End If

                ' Retrieve crc's from Bank 2
                If Bank = -1 Or Bank = 1 Then
                    packetAdr = Sectors(0).nAddress + BankSize
                    frame = New Comm.Comm_Frame(Comm.Comm_Frame.BikiFrameType.ID_FLASH_DATA _
                                                                          , packetAdr _
                                                                          , Comm.Comm_Frame.BikiFrameAction.READ, packetData, Comm.Comm_Frame.BikiFrameType.ID_FLASH_DATA)
                    If m_UsbCommHandler.SendFrame(frame, rcvData, , 10) = Comm.Comm_Frame.BikiFrameResponse.CMD_OK Then
                        Array.Copy(rcvData, 5, data, 0, packetSize)
                        For i As Integer = 0 To UBound(Sectors)
                            Sectors(i).nBank1CRC = System.BitConverter.ToUInt32(data, i * 4)
                        Next

                    End If
                End If

            Catch ex As Comm_Exceptions
                OnMessage(ex.Description)
                Return False
            End Try

            Return True
        End Function

        Protected Function BlankPacket(ByRef Packet() As Byte) As Boolean
            For i As UInt32 = 0 To UBound(Packet)
                If Packet(i) <> &HFF Then Return False
            Next
            Return True
        End Function

    End Class

End Namespace